#include "cvtclass_gener.hpp"

int CVTPkt_Gener::CVTClass_var_define(const Object& object)
{
	auto nameList = object.getMemberNames(); 
	for (auto& name : nameList)
	{
		auto& variant = name;
		auto& obj = object[variant];

		if (obj.isObject())
		{
			CVTClass_var_define(obj);
		}
		else if (obj.isArray())
		{
            string subObjectType = variant;
            subObjectType[0] = toupper(subObjectType[0]);			
			gen_format_write(m_hppstream,"  vector<%s> m_%s;	//%s",subObjectType.c_str(),variant.c_str());

			CVTPkt_Gener(subObjectType).CVTClass_execute(obj.get(0,nullObject));
		}
		else
		{
			if(variant.empty()) continue;
			gen_format_write(m_hppstream,"  string m_%s;	//%s",variant.c_str(),obj.asString().c_str());
		}		
	}
    gen_format_write(m_hppstream,"");	
	return 0;
}

int CVTPkt_Gener::CVTClass_function_convert_define(const Object& object)
{
	gen_format_write(m_hppstream,"  void toObject(Object& object);");
	gen_format_write(m_hppstream,"  void fromObject(const Object& object);");
	gen_format_write(m_hppstream,"");	
	return 0;
}

int CVTPkt_Gener::CVTClass_function_set_define(const Object& object)
{
	auto nameList = object.getMemberNames(); 
	for (auto& name : nameList)
	{
		auto& variant = name;
		auto& obj = object[variant];

		if (obj.isObject())
		{
			CVTClass_function_set_define(obj);
		}
		else if (obj.isArray())
		{
            string sFunctionName = variant;
            sFunctionName[0] = toupper(sFunctionName[0]);
			string subObjectType = 	sFunctionName;
			gen_format_write(m_hppstream,"  void set%s(const vector<%s>& %s); ",
				sFunctionName.c_str(),subObjectType.c_str(),variant.c_str());
		}
		else
		{
			if(variant.empty()) continue;
            string sFunctionName = variant;
            sFunctionName[0] = toupper(sFunctionName[0]);
			gen_format_write(m_hppstream,"  void set%s(const string& %s); ",sFunctionName.c_str(),variant.c_str());
		}		
	}
    gen_format_write(m_hppstream,"");
	return 0;
}

int CVTPkt_Gener::CVTClass_function_get_define(const Object& object)
{
	auto nameList = object.getMemberNames(); 
	for (auto& name : nameList)
	{
		auto& variant = name;
		auto& obj = object[variant];

		if (obj.isObject())
		{
			CVTClass_function_get_define(obj);
		}
		else if (obj.isArray())
		{
            string sFunctionName = variant;
            sFunctionName[0] = toupper(sFunctionName[0]);
			string subObjectType = 	sFunctionName;
			gen_format_write(m_hppstream,"  vector<%s>& get%s(); ",subObjectType.c_str(),sFunctionName.c_str());		
		}
		else
		{
			if(variant.empty()) continue;
            string sFunctionName = variant;
            sFunctionName[0] = toupper(sFunctionName[0]);
			gen_format_write(m_hppstream,"  string& get%s(); ",sFunctionName.c_str());
		}		
	}
    gen_format_write(m_hppstream,"");
	return 0;
}

int CVTPkt_Gener::CVTClass_function_convert_imp(const Object& object)
{
	//! define toObject function
	gen_format_write(m_cppstream,"void toObject(Object& object)");
	gen_format_write(m_cppstream,"{");
	{
		auto nameList = object.getMemberNames(); 
		for (auto& name : nameList)
		{
			auto& variant = name;
			auto& obj = object[variant];

			if (obj.isObject())
			{
				gen_format_write(m_cppstream,"  Object rowObj;");
				gen_format_write(m_cppstream,"  m_%s.toObject(rowObj);",variant.c_str());
				gen_format_write(m_cppstream,"  object[\"%s\"] = rowObj;",variant.c_str());
			}
			else if (obj.isArray())
			{
				gen_format_write(m_cppstream,"  Object arrayObj");
				gen_format_write(m_cppstream,"  for(auto& row : m_%s)",variant.c_str());
				gen_format_write(m_cppstream,"  {");
				gen_format_write(m_cppstream,"  	Object rowObj;");
				gen_format_write(m_cppstream,"  	row.toObject(rowObj);");
				gen_format_write(m_cppstream,"  	arrayObj.push(arrayObj);");
				gen_format_write(m_cppstream,"  }");
				gen_format_write(m_cppstream,"  object[\"%s\"] = arrayObj ;",variant.c_str());				
			}
			else
			{
				if(variant.empty()) continue;
				gen_format_write(m_cppstream,"  object[\"%s\"] = m_%s ;",variant.c_str(),variant.c_str());
			}		
		}	
	}
	gen_format_write(m_cppstream,"}\n");

	//! define toObject function
	gen_format_write(m_cppstream,"void fromObject(const Object& object)");
	gen_format_write(m_cppstream,"{");
	auto nameList = object.getMemberNames(); 
	{
		for (auto& name : nameList)
		{
			auto& variant = name;
			auto& obj = object[variant];

			if (obj.isObject())
			{
				gen_format_write(m_cppstream,"  Object rowObj = object.get(\"%s\");",variant.c_str());
				gen_format_write(m_cppstream,"  m_%s.fromObject(rowObj);",variant.c_str());
			}
			else if (obj.isArray())
			{
				string subObjectType = variant;
				subObjectType[0] = toupper(subObjectType[0]);   

				gen_format_write(m_cppstream,"  Object arrayObj = object.get(\"%s\");",variant.c_str());
				gen_format_write(m_cppstream,"  for (auto iter = arrayObj.begin(); iter != arrayObj.end(); iter++)");
				gen_format_write(m_cppstream,"  {");
				gen_format_write(m_cppstream,"  	auto& rowObj = *iter;");
				gen_format_write(m_cppstream,"  	%s %s;",subObjectType.c_str(),variant.c_str());
				gen_format_write(m_cppstream,"  	%s.fromObject(rowObj);",variant.c_str());
				gen_format_write(m_cppstream,"  	m_%s.push_back(%s);",variant.c_str(),variant.c_str());
				gen_format_write(m_cppstream,"  }");
			}
			else
			{
				if(variant.empty()) continue;
				gen_format_write(m_cppstream,"  m_%s = object.get(\"%s\"); ",variant.c_str(),variant.c_str());
			}		
		}
	}		
	gen_format_write(m_cppstream,"}\n");		
	return 0;
}

int CVTPkt_Gener::CVTClass_function_set_imp(const Object& object)
{
	auto nameList = object.getMemberNames(); 
	for (auto& name : nameList)
	{
		auto& variant = name;
		auto& obj = object[variant];

		if (obj.isObject())
		{
			CVTClass_function_set_imp(obj);
		}
		else if (obj.isArray())
		{
            string sFunctionName = variant;
            sFunctionName[0] = toupper(sFunctionName[0]);     
			string subObjectType = 	sFunctionName;

			gen_format_write(m_cppstream,"void %s::set%s(const vector<%s>& %s) ",
				m_className.c_str(),sFunctionName.c_str(),subObjectType.c_str(),variant.c_str());
            gen_format_write(m_cppstream,"{");
            gen_format_write(m_cppstream,"  m_%s = %s ;",variant.c_str(),variant.c_str());
            gen_format_write(m_cppstream,"}");
            gen_format_write(m_cppstream,"");
		}
		else
		{
			if(variant.empty()) continue;
            string sFunctionName = variant;
            sFunctionName[0] = toupper(sFunctionName[0]);            
			gen_format_write(m_cppstream,"void %s::set%s(const string& %s) ",
				m_className.c_str(),sFunctionName.c_str(),variant.c_str());
            gen_format_write(m_cppstream,"{");
            gen_format_write(m_cppstream,"  m_%s = %s ;",variant.c_str(),variant.c_str());
            gen_format_write(m_cppstream,"}");
            gen_format_write(m_cppstream,"");
		}		
	}
    gen_format_write(m_cppstream,"");	
	return 0;
}

int CVTPkt_Gener::CVTClass_function_get_imp(const Object& object)
{
	auto nameList = object.getMemberNames(); 
	for (auto& name : nameList)
	{
		auto& variant = name;
		auto& obj = object[variant];

		if (obj.isObject())
		{
			CVTClass_function_get_imp(obj);
		}
		else if (obj.isArray())
		{
            string sFunctionName = variant;
            sFunctionName[0] = toupper(sFunctionName[0]);    
			string subObjectType = 	sFunctionName;

			gen_format_write(m_cppstream,"vector<%s>& %s::get%s() ",
				subObjectType.c_str(),m_className.c_str(),sFunctionName.c_str());
            gen_format_write(m_cppstream,"{");
            gen_format_write(m_cppstream,"  return m_%s;",variant.c_str());
            gen_format_write(m_cppstream,"}");
            gen_format_write(m_cppstream,"");			
		}
		else
		{
			if(variant.empty()) continue;
            string sFunctionName = variant;
            sFunctionName[0] = toupper(sFunctionName[0]);            
			gen_format_write(m_cppstream,"string& %s::get%s() ",m_className.c_str(),sFunctionName.c_str());
            gen_format_write(m_cppstream,"{");
            gen_format_write(m_cppstream,"  return m_%s;",variant.c_str());
            gen_format_write(m_cppstream,"}");
            gen_format_write(m_cppstream,"");
		}		
	}	
    gen_format_write(m_cppstream,"");
	return 0;
}

int CVTPkt_Gener::CVTClass_gen_hpp(const Object& object)
{
    gen_format_write(m_hppstream,"#pragma once");
    gen_format_write(m_hppstream,"");

    gen_format_write(m_hppstream,"#include <string>");
    gen_format_write(m_hppstream,"#include <cstdlib>");
    gen_format_write(m_hppstream,"#include <cstdio>");
	gen_format_write(m_hppstream,"#include <string>");
	gen_format_write(m_hppstream,"#include <vector>");
	gen_format_write(m_hppstream,"using namespace std;");
    gen_format_write(m_hppstream,"");

    gen_format_write(m_hppstream,"#include \"logcplus/logcplus.h\"");
    gen_format_write(m_hppstream,"#include \"topbase/topbase.hpp\"");
    gen_format_write(m_hppstream,"#include \"topcvt/topcvt.hpp\"");
    gen_format_write(m_hppstream,"");

    gen_format_write(m_hppstream,"class %s",m_className.c_str());
    gen_format_write(m_hppstream,"{");
    gen_format_write(m_hppstream,"private:");

    CVTClass_var_define(object);

    gen_format_write(m_hppstream,"public:");
    gen_format_write(m_hppstream,"  %s()=default;",m_className.c_str());
    gen_format_write(m_hppstream,"  ~%s()=default;",m_className.c_str());
    gen_format_write(m_hppstream,"");
    gen_format_write(m_hppstream,"public:");

    CVTClass_function_set_define(object);
    CVTClass_function_get_define(object);

	CVTClass_function_convert_define(object);

    gen_format_write(m_hppstream,"};");
    gen_format_write(m_hppstream,"");
    return 0;
}

int CVTPkt_Gener::CVTClass_gen_cpp(const Object& object)
{
	gen_format_write(m_cppstream,"#include \"%s.hpp\"",m_className.c_str());
	gen_format_write(m_cppstream,"\n");

    CVTClass_function_set_imp(object);
    CVTClass_function_get_imp(object);

	CVTClass_function_convert_imp(object);
    return 0;
}

int CVTPkt_Gener::CVTClass_execute(const Object& object)
{
	string hpp_file,cpp_file;

	hpp_file.append(m_className).append(".hpp");
	cpp_file.append(m_className).append(".cpp");

	m_hppstream.open(hpp_file);
	m_cppstream.open(cpp_file);

    CVTClass_gen_hpp(object);
    CVTClass_gen_cpp(object);

	infoLog("CVTClass_execute [%s] [%s] succed.",hpp_file.c_str(),cpp_file.c_str());

    return 0;
}